package logger

import (
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"io"
	"os"
	"time"
)

var (
	logger *zap.SugaredLogger
)

func init() {
	// (JSON Format) {"level":"INFO","ts":"2021-12-17 13:51:44","file":"logger/log.go:74","msg":"[gRPC SDK] started successfully"}
	encoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
		LevelKey:    "level",
		EncodeLevel: zapcore.CapitalLevelEncoder,
		TimeKey:     "ts",
		EncodeTime: func(time time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(time.Format("2006-01-02 15:04:05"))
		},
		CallerKey:    "file",
		EncodeCaller: zapcore.ShortCallerEncoder,
		MessageKey:   "msg",
		EncodeDuration: func(duration time.Duration, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendInt64(int64(duration) / 1e6)
		},
	})
	debugLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
		return level >= zapcore.DebugLevel
	})
	infoLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
		return level >= zapcore.InfoLevel
	})
	errorLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
		return level >= zapcore.ErrorLevel
	})
	infoHook := getRotateHook("./logs/info")
	errorHook := getRotateHook("./logs/error")
	core := zapcore.NewTee(
		// info log-file
		zapcore.NewCore(encoder, zapcore.AddSync(infoHook), infoLevel),
		// error log-file
		zapcore.NewCore(encoder, zapcore.AddSync(errorHook), errorLevel),
		// error std-out
		zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), debugLevel),
	)
	log := zap.New(core, zap.AddCaller())
	logger = log.Sugar()
}

func getRotateHook(f string) io.Writer {
	hook, err := rotatelogs.New(
		f+"-%Y%m%d%H.log",
		// create soft link (Linux)
		// rotatelogs.WithLinkName(f),
		// save the log within 7 days
		rotatelogs.WithMaxAge(time.Hour*24*7),
		// split the log in each hour
		rotatelogs.WithRotationTime(time.Hour),
	)
	if err != nil {
		panic(err)
	}
	return hook
}

func GetLogger() *zap.SugaredLogger {
	return logger
}
